package com.dormitory.management.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dormitory.management.system.entity.*;
import com.dormitory.management.system.enums.UserEnum;
import com.dormitory.management.system.mapper.*;
import com.dormitory.management.system.req.RoomPageReq;
import com.dormitory.management.system.req.RoomSaveBatchReq;
import com.dormitory.management.system.req.RoomSaveReq;
import com.dormitory.management.system.req.RoomUpdateReq;
import com.dormitory.management.system.resp.HousemasterResp;
import com.dormitory.management.system.resp.RoomResp;
import com.dormitory.management.system.req.*;
import com.dormitory.management.system.service.HousemasterService;
import com.dormitory.management.system.service.RoomService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dormitory.management.system.service.UserService;
import com.dormitory.managemnet.util.utils.BeanUtil;
import com.google.errorprone.annotations.Var;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 房间表 服务实现类
 * </p>
 *
 * @author
 * @since 2021-12-17
 */
@Service
public class RoomServiceImpl extends ServiceImpl<RoomMapper, Room> implements RoomService {

    @Autowired
    private BuildingMapper buildingMapper;
    @Autowired
    private LivingMapper livingMapper;
    @Autowired
    private StudentMapper studentMapper;
    @Autowired
    private HousemasterService housemasterService;
    @Autowired
    private HousemasterMapper housemasterMapper;
    @Autowired
    private UserService userService;

    @Override
    @Transactional
    public boolean save(RoomSaveReq req) {
        if(this.baseMapper.insert(BeanUtil.copyProperties(req, Room.class))>0){
            if( buildingMapper.update(null, new UpdateWrapper<Building>().lambda()
                    .setSql("num_room=num_room+1")
                    .eq(Building::getId, req.getBuildingId()))>0){
                Building building = buildingMapper.selectById(req.getBuildingId());
                return livingMapper.update(null,new UpdateWrapper<Living>().lambda()
                        .setSql("num_room=num_room+1")
                        .eq(Living::getId, building.getLivingId()))>0;
            }
            return false;
        }
        return false;
    }

    @Override
    @Transactional
    public boolean saveBatch(RoomSaveBatchReq req) {
        for(int i=1;i<=req.getBuildingNum();i++){
            for(int j=1;j<=req.getRoomNum();j++){
                Room room = BeanUtil.copyProperties(req, Room.class);
                room.setRoom(i*100+j);
                if(this.baseMapper.insert(room)>0){
                    if( buildingMapper.update(null, new UpdateWrapper<Building>().lambda()
                            .setSql("num_room=num_room+1")
                            .eq(Building::getId, req.getBuildingId()))>0){
                        Building building = buildingMapper.selectById(req.getBuildingId());
                        livingMapper.update(null,new UpdateWrapper<Living>().lambda()
                                .setSql("num_room=num_room+1")
                                .eq(Living::getId, building.getLivingId()));
                    }
                }
            }
        }
        return true;
    }

    @Override
    public boolean saveLeader(RoomSaveLeaderReq req) {
        Room room = new Room();
        room.setId(req.getId());
        room.setLeaderId(req.getStuId());
        return this.baseMapper.updateById(room)>0;
    }


    @Override
    @Transactional
    public boolean delete(Long id) {
        Room room = this.baseMapper.selectById(id);
        if(this.baseMapper.deleteById(id)>0){
            if( buildingMapper.update(null, new UpdateWrapper<Building>().lambda()
                    .setSql("num_room=num_room-1")
                    .eq(Building::getId, room.getBuildingId()))>0){
                Building building = buildingMapper.selectById(room.getBuildingId());
                if(livingMapper.update(null,new UpdateWrapper<Living>().lambda()
                        .setSql("num_room=num_room-1")
                        .eq(Living::getId, building.getLivingId()))>0){
                    studentMapper.update(null,new UpdateWrapper<Student>().lambda()
                            .set(Student::getRoomId,null)
                            .eq(Student::getRoomId,id));
                    housemasterMapper.update(null,new UpdateWrapper<Housemaster>().lambda()
                            .set(Housemaster::getRoomId,null)
                            .eq(Housemaster::getRoomId,id));
                    return true;

                }
                return false;
            }
            return false;
        }
        return false;
    }

    @Override
    @Transactional
    public boolean deleteAll(Long id) {
        Building building = buildingMapper.selectById(id);
        List<Room> list = this.baseMapper.selectList(new QueryWrapper<Room>().lambda().eq(Room::getBuildingId, id));
        for (Room room : list) {
            studentMapper.update(null,new UpdateWrapper<Student>().lambda()
                    .set(Student::getRoomId,null)
                    .eq(Student::getRoomId,room.getId()));
            housemasterMapper.update(null,new UpdateWrapper<Housemaster>().lambda()
                    .set(Housemaster::getRoomId,null)
                    .eq(Housemaster::getRoomId,room.getId()));
        }
        if(this.baseMapper.delete(new QueryWrapper<Room>().lambda().eq(Room::getBuildingId, id))>0){
            if( buildingMapper.update(null, new UpdateWrapper<Building>().lambda()
                    .set(Building::getNumRoom,0)
                    .eq(Building::getId, building.getId()))>0){
                return livingMapper.update(null,new UpdateWrapper<Living>().lambda()
                        .setSql("num_room=num_room-"+building.getNumRoom())
                        .eq(Living::getId, building.getLivingId()))>0;
            }
            return false;
        }
        return false;
    }

    @Override
    public boolean update(RoomUpdateReq req) {
        return this.baseMapper.updateById(BeanUtil.copyProperties(req,Room.class))>0;
    }

    @Override
    public IPage<RoomResp> getPage(RoomPageReq req) {
        QueryWrapper<RoomResp> wrapper = new QueryWrapper<RoomResp>()
                .eq(req.getRoom() != null, "room", req.getRoom())
                .eq(req.getBuildingId() != null, "r.building_id", req.getBuildingId())
                .eq(req.getLivingId() != null, "b.living_id", req.getLivingId());
        if(req.getStatus()!=null&&req.getStatus()==0){
            wrapper.apply("current_number<total_number");
        }if (req.getStatus()!=null&&req.getStatus()==1){
            wrapper.apply("current_number=total_number");
        }
        if (userService.getRoleKey(req.getUsername()).equals(UserEnum.USER_HOUSEMASTER.getRoleKey())) {
            Housemaster housemaster = housemasterMapper.selectOne(new QueryWrapper<Housemaster>().lambda().eq(Housemaster::getIdentityCard, req.getUsername()));
            wrapper.eq("r.building_id",housemaster.getBuildingId());
        }
        return this.baseMapper.getRoomPage(new Page<>(req.getPageCurrent(),req.getPageSize()), wrapper);
    }

    @Override
    public List<RoomResp> getList(Long id) {
        List<RoomResp> resultList = new ArrayList<>();
        List<Room> list = this.baseMapper.selectList(new QueryWrapper<Room>()
                .eq("building_id", id)
                .apply("current_number<total_number"));
        for (Room room : list) {
            RoomResp roomResp = BeanUtil.copyProperties(room, RoomResp.class);
            roomResp.setSpareNumber(roomResp.getTotalNumber()-roomResp.getCurrentNumber());
            resultList.add(roomResp);
        }
        return resultList;
    }

    @Override
    public List<Student> getStuList(Long id) {
        return this.studentMapper.selectList(new QueryWrapper<Student>().lambda().eq(Student::getRoomId,id));
    }


}
